/*!  \file  TriEigen.h
 *	  \brief defines TriEigen class interface for computing eigen decomposition of symetric tridiagonal matrix 
 * 
 *   \details   details
 *   \author    Yordan Madzhunkov German Research School for Simulation Sciences GmbH
 *   \version   1.0
 *   \date      07/02/2013 04:11:40 PM
 *   \copyright GNU Public License.
 */
#pragma once
#include "ImplementationFactory.h"
#include "UnitTester.h"
class TriEigen : public Implementation { // interface for tridiagonal symetric eigenvalue problem
public:
	// Computes the eigen values/vectors of symmetric tridiagonal matrix T
	// T Q =  Sigma * Q
	// T is a Symetric Tridiagonal Matrix
	// Q are orthogonal matrices
	// Sigma is diagonal Matrix
	virtual void compute(const Matrix & T, Matrix & Sigma, Matrix & Q ) = 0;
	TriEigen(const char * name_): Implementation(name_, TriEigenGroup) {
		setCompileTime(__DATE__, __TIME__);
		canComputeRange = aColMajor = aRowMajor = false;
	};
	virtual void computeRange( const Matrix & T, Matrix & Sigma, Matrix & Q, 
	const int indexLow, const int indexUp); 
	bool aColMajor, aRowMajor, canComputeRange;
};


#define TRIEIGEN(x) \
class x : public TriEigen { \
public: \
	x();\
	virtual ~x(){}; \
	virtual void compute(const Matrix & T, Matrix & Sigma, Matrix & Q );\
	virtual bool setNumberOfThreads(const int nThreads_);\
};
#define TRIEIGEN_RANGE(x) \
class x : public TriEigen { \
public: \
	x();\
	virtual ~x(){}; \
	virtual void compute(const Matrix & T, Matrix & Sigma, Matrix & Q );\
	virtual void computeRange( const Matrix & T, Matrix & Sigma, Matrix & Q, \
	const int indexLow, const int indexUp); \
	virtual bool setNumberOfThreads(const int nThreads_);\
};

class TriEigenUnitTest : public UnitTest { 
public: 
	TriEigenUnitTest ( TriEigen &); 
	virtual ~TriEigenUnitTest (){}; 
	virtual bool test() const; 
private:
	DISALLOW_COPY_AND_ASSIGN(TriEigenUnitTest);
	bool checkNorms( const Matrix & T, const Matrix & S, const Matrix & Q, const double limit) const;
	TriEigen & ev;
};
